function MapManager() {
    //INIZIO COSTRUTTORE ------------------------------------------------------
    /*
     * codice per l'inizializzazione della variabile mappa all'interno del programma
     */
    this.constant_mapCenter= new google.maps.LatLng(44.40717, 8.93060);//Genova
    this.constant_zoomLevel=15;
    this.constant_mapType=google.maps.MapTypeId.ROADMAP;
    this.constant_divDisplayMap=null;
    this.placesList=Array();
    this.placedEventsList=Array();
    this.timeDistance=Array();//caching delle distanze di percorrenza (a piedi) e dei relativi 
    this.map=null;
    this.familyTy=1;
    
    /*
     * codice per l'inizializzazione degli oggetti necessari alla visualizzazione
     * dei percorsi all'interno della mappa.
     */
    this.directionsDisplay = new google.maps.DirectionsRenderer({
        suppressMarkers:true
    });
    this.alternativeDirectionDisplay = new google.maps.DirectionsRenderer({
        suppressMarkers:true
    });
    this.directionsService= new google.maps.DirectionsService();
    

    //FINE COSTRUTTORE ---------------------------------------------------------
    /**
     * mostra la mappa all'inizio del programma
     */
    this.displayMap=function(){
        this.map = new google.maps.Map(document.getElementById(this.constant_divDisplayMap),{ 
            zoom:this.constant_zoomLevel,
            mapTypeId: this.constant_mapType,
            center: this.constant_mapCenter
        });
    //        this.directionsDisplay.setMap(this.map);
    //        this.alternativeDirectionDisplay.setMap(this.map);
    }

    /**
     * Funzione che permette di mostrare i markers in funzione degli eventi
     * passati in input
     */
    this.viewPlaces=function(evtlist){
        this.hideAllMarkers();
        this.generatePlaces(evtlist);
        //nascondo tutte le (unica) finestre
        this.placedEventsList=Array();
        for(var i in evtlist){
            if(!isNaN(i)){
                ev=evtlist[i];
                this.placesList[ev['id_luogo']]['marker'].setVisible(true);
                this.placesList[ev['id_luogo']]['eventi']=new Array();
                if(this.placedEventsList[ev['id_luogo']]==null)
                    this.placedEventsList[ev['id_luogo']]=new Array();
                this.placedEventsList[ev['id_luogo']].push(ev);
            }
        }
    //alert(dump(this.placedEventsList));
    }


    /**
     * funzione che permette di nascondere tutti i path visualizzati.
     * in futuro forse è meglio pensare  a una serie di path visualizzabili/
     * rimovibili dalla visualizzazione
     */
    this.hideAllPaths=function(){
        this.alternativeDirectionDisplay.setMap(null);
        this.directionsDisplay.setMap(null);
    }
    /**
     * metodo che ricava i nuovi luoghi(dotati di nome, lat, lonm marker e id)
     * a partire da una lista di eventi. Se il luogo è già presente non viene
     * rigenerato.
     */
    this.generatePlaces=function(evtlist){
        var ev,idl,path_ico;
        //alert("ciaop");
        //alert(dump(evtlist));
        for(var i in evtlist){
            if(!isNaN(i)){
                ev=evtlist[i];
                try{
                    idl=ev['id_luogo'];
                } catch(e){
                    alert("i="+i+" eerr="+dump(ev));
                }
                if(this.placesList[idl]==null){
                    //                    if(i==10001)
                    //                        alert("III");
                    //creo array
                    //alert(dump(ev));
                    //var idl=ev['id_luogo'];
                    this.placesList[idl]=Array();
                    this.placesList[idl]['nome']=ev['nome_luogo'];
                    this.placesList[idl]['id']=ev['id_luogo'];
                    this.placesList[idl]['lat']=ev['lat'];
                    this.placesList[idl]['lon']=ev['lon'];
                    this.placesList[idl]['latlng']=new google.maps.LatLng(ev['lat'],ev['lon']);

                    //inizio gestione immagini categorie
                    path_ico="";
                    //todo:trovare un modo furbo per la gestione delle icone =>priorità...
                    if(ev['priorityIconUrl']){
                        path_ico=ev['priorityIconUrl'];
                    } else{
                        for(var j in ev['categorie']){
                            if(!isNaN(j) && ev['categorie'][j]['famiglia_id']==this.familyTy){
                                //path_ico=ev['categorie'][j]['path_icona'];
                                path_ico=poiman.getCategoryIcon(ev['categorie'][j]['famiglia_id'], ev['categorie'][j]['categoria_id']);
                            }
                        }
                    }
                    //if(i==10001) alert(dump(this.placesList[idl]));
                    //fine gestione immagini categorie
                    var myLatlng = new google.maps.LatLng(ev['lat'], ev['lon']);
                    if(path_ico!="")
                        this.placesList[idl]['marker']=
                        new google.maps.Marker({
                            position: myLatlng,
                            map: this.map,
                            icon:path_ico
                        });
                    else this.placesList[idl]['marker']=
                        new google.maps.Marker({
                            position: myLatlng,
                            map: this.map
                        });
                    this.appoggio(idl, this.placesList[idl]['marker']);
                }
                else{
                    //inizio gestione immagini categorie
                    path_ico="";
                    //todo:trovare un modo furbo per la gestione delle icone =>priorità...
                    if(ev['priorityIconUrl']){
                        path_ico=ev['priorityIconUrl'];
                    } else{
                        for(var j in ev['categorie']){
                            if(!isNaN(j) && ev['categorie'][j]['famiglia_id']==this.familyTy){
                                //path_ico=ev['categorie'][j]['path_icona'];
                                path_ico=poiman.getCategoryIcon(ev['categorie'][j]['famiglia_id'], ev['categorie'][j]['categoria_id']);
                            }
                        }
                    }
                    //if(i==10001) alert(dump(this.placesList[idl]));
                    //fine gestione immagini categorie
                    if(path_ico!="")
                        this.placesList[idl]['marker'].icon=path_ico;
                    this.appoggio(idl, this.placesList[idl]['marker']);
                }
            }
        }
    }
    /**
     * funzione che permette di memorizzare temporaneamente idl per ciascun
     * marker, storie di stack, di preset di variabili e storie del genere, meglio
     * non chiedere
     */
    this.appoggio=function(idl,marker){
        google.maps.event.addListener(marker, "click", function(){
            mapman.markerPressed(idl);
        });
    }

    /**
     * Nasconde tutti i markers visualizzati sulla mappa
     */
    this.hideAllMarkers=function(){
        for(var i in this.placesList){
            if(!isNaN(i)){
                this.placesList[i]['marker'].setVisible(false);
            }
        }
    }

    this.updateDistances=function(startLocString,endLocString,duration,res){
        if(!mapman.timeDistance[startLocString])
            mapman.timeDistance[startLocString]=Array();
        if(!mapman.timeDistance[startLocString][endLocString])
            mapman.timeDistance[startLocString][endLocString]=Array();
        mapman.timeDistance[startLocString][endLocString]['time']=duration;
        mapman.timeDistance[startLocString][endLocString]['route']=res;
    }
    /**
     * restituisce il tempo necessario a raggiungere (a piedi) il punto
     * identificato dalle coordinate lat2, lon2 a partire da quello identificato
     * dalle coordinate lat1, lon1
     */
    this.getTimeBetweenPoints=function(latlon1,latlon2,idEvt,callback){
        startLocString="lat:"+latlon1.lat()+" lon:"+latlon1.lng();
        endLocString="lat:"+latlon2.lat()+" lon:"+latlon2.lng();
        if(!mapman.timeDistance[startLocString]||!mapman.timeDistance[startLocString][endLocString]){
            this.directionsService.route({
                origin:latlon1,
                destination:latlon2,
                travelMode: google.maps.DirectionsTravelMode.WALKING
            },
            function(res,stat){
                var duration=0;
                if(stat==google.maps.DirectionsStatus.OK){
                    for(var j in res.routes){
                        if(!isNaN(j)){
                            for(var k in res.routes[j].legs){
                                if(!isNaN(k)){
                                    duration+=res.routes[j].legs[k].duration.value;
                                    break;
                                }
                            }
                            break;
                        }
                    }
                    mapman.updateDistances(startLocString,endLocString,duration,res);
                    callback(idEvt);
                }
            });
            return null;
        } else return mapman.timeDistance[startLocString][endLocString]['time'];
    }

    /**
     * disegna un percorso tra punti appartenenti ad una request
     */
    this.drawPathFromMapsResource=function(res){
        mapman.directionsDisplay.setMap(this.map);
        mapman.directionsDisplay.setDirections(res);
    }
    /**
     * cancella il path MapsResource
     */
    this.clearPathFromMapsResource=function(){
        mapman.directionsDisplay.setMap(null);
    }

    /**
     * disegna un percorso tra i due punti
     */
    this.drawPathBetweenTwoPoints=function(latLng1, latLng2){
        this.directionsService.route({
            origin:latLng1,
            destination:latLng2,
            travelMode: google.maps.DirectionsTravelMode.WALKING,
            unitSystem: google.maps.DirectionsUnitSystem.METRIC
        },
        function(result, status) {
            if (status == google.maps.DirectionsStatus.OK) {
                mapman.drawPathFromMapsResource(result);
            }
        });
    }
    /**
     * funzione di callback che permette di visualizzare un evento all'interno
     * del fumetto... sarebbe meglio metterla nel controller
     */
    this.markerPressed= function(idLuogo){
        graphman.loadEvtsInWin(idLuogo);
    //        if(phcman.getStatus()==phcman.STAT_CREATING_PATH){
    //            //mapman.getTimeBetweenPoints(latlon1, latlon2);
    //        }
    }

    
    this.viewPathFromEvts=function(){
        var evts=pathman.getPathToShow();
        var arrPath=Array();
        //alert(dump(evts));
        if(evts.lat!=0 && evts.lon!=0){
            arrPath.push(new google.maps.LatLng(evts.lat,evts.lon));
        //alert(evts.lat+ " "+evts.lon);
        }
        for(var j in evts['eventi']){
            if(!isNaN(j)){
                arrPath.push(new google.maps.LatLng(
                    evtman.eventList[evts['eventi'][j]['id']]['lat'],
                    evtman.eventList[evts['eventi'][j]['id']]['lon']
                    ));
            }
        }
        mapman.viewPathFromLatLon(arrPath);
    }

    this.viewPathFromPathman=function(){
    //mapman.viewPath(pathman.getPathToShow());
    }

    /**
     * Funzione che permette di aggiungere un punto al percorso e di visualizzare
     * il percorso completo su mappa.
     */
    this.addPoint=function(evtid, orarid){
        phcman.addPoint(evtid, orarid);
        mapman.viewPathFromLatLon(phcman.getPathCoordinates());
        graphman.redrawNewPathDiv();
    }
    /**
     * Funzione che permette di aggiungere un punto al percorso e di visualizzare
     * il percorso completo su mappa.
     */
    this.reloadCreatedPath=function(){
        mapman.viewPathFromLatLon(phcman.getPathCoordinates());
        graphman.redrawNewPathDiv();
    }

    /**
     * funzione che permette di disegnare un percorso
     * TODO: da inserire ancora la richiesta dei singoli eventi che vengono
     * visualizzati all'interno del percorso.
     */
    this.viewPath=function(inpath){
        var wayPts=new Array();
        var status="inizio";
        var pathToShow=inpath;//arr latlon
        var first=true;
        var tmpObj;
        var k;
        try{
            if(pathToShow!=null){
                //alert(dump(evtman.eventList));
                //1 for che crea la lista di waypoints
                status="create req";
                req={
                    provideRouteAlternatives: false,
                    travelMode: google.maps.DirectionsTravelMode.WALKING,
                    unitSystem: google.maps.DirectionsUnitSystem.METRIC
                }
                //alert("Cissao");
                status="add waypoints";
                for(var j in pathToShow['eventi']){
                    if(!isNaN(j)){
                        if(first){
                            req.origin=new google.maps.LatLng(
                                evtman.eventList[pathToShow['eventi'][j]['id']]['lat'],
                                evtman.eventList[pathToShow['eventi'][j]['id']]['lon']
                                );
                            first=false;
                        } else {
                            tmpObj=new Object();
                            tmpObj.location=new google.maps.LatLng(
                                evtman.eventList[pathToShow['eventi'][j]['id']]['lat'],
                                evtman.eventList[pathToShow['eventi'][j]['id']]['lon']
                                );
                            tmpObj.stopover=true;
                            wayPts.push(tmpObj);
                        }
                    }
                }
                
                //req.destination= wayPts.pop();
                var arrival=wayPts.pop();
                if(wayPts.length>0){
                    req.waypoints=Array();
                    for(k in wayPts){
                        if((!isNaN(k))){
                            req.waypoints.push(wayPts[k]);
                        }
                    }
                }
                req.destination=arrival.location;
                //alert(dump(req));
                //alert(dump(mapman.directionsService));
                
                status="direction request";
                mapman.directionsService.route(req,
                    function(result, status) {
                        if (status == google.maps.DirectionsStatus.OK) {
                            mapman.drawPathFromMapsResource(result);
                        }
                    });
            }
        } catch(err) {
            alert("errore in viewPath("+status+"):"+err);
            alert(dump(err));
        }
    }

    /**
     * Permette di visualizzare un percorso a partire da una lista di coordinate.
     * Il percorso verrà mostrato senza markers.
     *
     */
    this.viewPathFromLatLon=function(inpath){
        //alert("viuo");
        var wayPts=new Array();
        var status="inizio";
        var pathToShow=inpath;//arr latlon
        //alert(dump(inpath));
        var first=true;
        var k;
        //alert("ino");
        try{
            if(pathToShow!=null){
                status="create req";
                req={
                    provideRouteAlternatives: false,
                    travelMode: google.maps.DirectionsTravelMode.WALKING,
                    unitSystem: google.maps.DirectionsUnitSystem.METRIC
                }
                //alert("Cissao");
                status="add waypoints";
                for(var j in pathToShow){
                    if(!isNaN(j)){
                        if(first){
                            req.origin=pathToShow[j];
                            first=false;
                        } else {
                            var tmpObj={
                                location:pathToShow[j],
                                stopover:true
                            }
                            wayPts.push(tmpObj);
                        }
                    }
                }
                var arrival=wayPts.pop();
                if(wayPts.length>0){
                    req.waypoints=Array();
                    for(k in wayPts){
                        if((!isNaN(k))){
                            req.waypoints.push(wayPts[k]);
                        }
                    }
                }
                status="createDestination";
                //alert(dump(arrival));
                if(arrival!=null){
                    req.destination=new google.maps.LatLng(arrival.location.lat(),arrival.location.lng());//non e' già latlng
                    status="direction request";
                    //alert(dump(req));
                    mapman.directionsService.route(req,
                        function(result, status) {
                            if (status == google.maps.DirectionsStatus.OK) {
                                mapman.drawPathFromMapsResource(result);
                            //alert(dump(result));
                            } else alert("errore: "+status);
                        });
                } else {
                    this.clearPathFromMapsResource();
                }
            }
        } catch(err) {
            alert("errore in viewPathFromLatLon("+status+"):"+err);
        }
    }
}